<template>
  <div class="full" style="background: white" v-loading="loading">
    <el-menu style="height: 100%;width: 10%;float: left;" class="el-menu-vertical-demo">
      <el-menu-item
          v-for="contact in contactList"
          :index="contact.casId + ''"
          @click="tabClick(contact.casId)"
          :ref="(el) => contact.ref = el ">
        <template #title>{{ contact.name }}</template>
      </el-menu-item>
    </el-menu>
    <!-- <div style="float: left;">123</div> -->
    <div
        v-if="activeContact != null"
        style="height: 100%;width: 90%; float: left;"
        ref="chatContent"
    >
      <div
          style="margin-right: 7px;height: 80%;overflow:auto"
          id="chatContent"
          @scroll="handleScroll"
      >
        <div>
          <img
              v-if="activeContact.loading"
              style="margin-right: auto; margin-left: auto;"
              src="/src/assets/loading.gif"
              alt="网络错误"
          />
          <div v-if="activeContact.isEnd" class="el-empty__description">
            <p>已经到底了</p>
          </div>
        </div>
        <div
            v-if="activeContact != null"
            v-for="msg in activeContact.msgList"
            :style="{ float: msg.isSelfSend ? 'right' : 'left' }"
            style="width: 80%;margin: 10px;"
        >
          <el-tag
              :style="{ float: msg.isSelfSend ? 'right' : 'left' }"
              :type="msg.isSelfSend ? '' : 'info'"
          >{{ msg.content }}
          </el-tag>
          <br/>
          <br/>
        </div>
      </div>

      <div style="height:20%">
        <div style="float:right;width: 100%;">
          <el-input
              style="width:90%"
              v-model="sendText"
              :rows="2"
              type="textarea"
              placeholder="Please input"
          />
          <emoji @selectEmoji="handleEmojiClick"></emoji>
          <el-button type="primary" @click="sendMsg">确认发送</el-button>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import io from "socket.io-client"
import emoji from "./Emoji.vue";
import {computed, nextTick, onBeforeUpdate, onMounted, onUpdated, ref, shallowRef, watch} from "vue";
import {onBeforeRouteUpdate, useRoute} from "vue-router";
import {getRole, localGet, localRemove, localSet} from "~/config/utils.js";
import {localKeys} from "~/config/const.js";
import axios from "~/config/axios.js";
import router from "~/config/router.js";
import {ElMessage} from "element-plus";
import {newCasId} from "~/config/state.js"

const handleEmojiClick = (e) => {
  sendText.value = sendText.value + e
}

const contactList = ref([])
const sendText = ref('')

const role = getRole(useRoute().path)
let socket = undefined;
let token = localGet(localKeys[role].token)
let myCasId = localGet(localKeys[role].casId)
let hasGenToken = false
const connected = ref(false)
const activeContact = ref()
const loading = ref(true)

// ---------------------------------newCasId----------------------------------------------
watch(newCasId, () => {
  newContact()
})
const newContact = () => {
  if (socket.connected && newCasId.value !== undefined && newCasId.value !== '') {
    const casId = newCasId.value
    newCasId.value = undefined
    for (const i in contactList.value) {
      if (contactList.value[i].casId == casId) {
        nextTick(() => {
          contactList.value[i].ref.$el.click()
        })
        return
      }
    }
    socket.emit("person_info", casId, (res) => {
      if (res.code == 200) {
        const newContact = {casId: casId, name: res.data}
        initContact(newContact)
        contactList.value.push(newContact)
        nextTick(() => {
          newContact.ref.$el.click()
        })
      } else {
        ElMessage.error("联系人不存在")
      }
    })
  }
}
// ----------------connect------------------------------------------
const realConnect = () => {
  socket = io("http://localhost:8082", {
    transports: ['websocket'],
    query: `token=${token}`,
    forceNew: true
  });

  const onevent = socket.onevent;
  socket.onevent = function (packet) {
    const args = packet.data || [];
    onevent.call(this, packet);    // original call
    packet.data = ["*"].concat(args);
    onevent.call(this, packet);      // additional call to catch-all
  };
  socket.on("*", function (event, data, callBack) {
    if (callBack != null) {
      callBack.call(callBack, null)
    }
    if (data.code == 200) {
      data = data.data
    }
  });
  socket.on("connect", () => {
    console.log("connected");
    connected.value = true
    loading.value = false
    localSet(localKeys[role].token, token)
    localSet(localKeys[role].casId, myCasId)
  });
  socket.on('reconnect_attempt', (attemptNumber) => {
    // if (attemptNumber > 3) {
    // }
    localRemove(localKeys[role].token)
    localRemove(localKeys[role].casId)
    token = undefined
    myCasId = undefined
    socket.close();
    if (!hasGenToken) {
      tryConnect();
    } else {
      loading.value = false
      ElMessage.error("出现异常")
    }
  })
  socket.on("push_msg", (data) => {
    dealMsg([data], data.fromUser, false)
    toBottom()
  })

  socket.on("push_unread_msg", (msg) => {
    console.log(msg);
  })
}
const tryConnect = async () => {
  if (token) {
    realConnect()
  } else {
    const {token: newToken, casId} = await axios.get(`/genCasToken/${role}`)
    if (typeof newToken === 'string') {
      hasGenToken = true
      token = newToken
      myCasId = casId
      realConnect()
    } else {
      await router.push("/")
    }
  }
}
tryConnect()
watch(connected, () => {
  socket.emit("contact_list", {}, ({data}) => {
    contactList.value = data.contactList
    contactList.value.forEach(initContact);
    newContact()
  })
})
// --------------------------------util-----------------------------------
const initContact = (contact) => {
  contact.isEnd = false
  contact.loading = true
  contact.beforeSendId = null
  contact.beforeReceiveId = null
  contact.sendIdSet = new Set()
  contact.receiveIdSet = new Set()
  contact.msgList = []
}
// --------------------------------msg---------------------------------------------
const fetchMsgHistory = () => {

  const request = {
    contactCasId: activeContact.value.casId,
    beforeSendId: activeContact.value.beforeSendId,
    beforeReceiveId: activeContact.value.beforeReceiveId
  };
  activeContact.value.loading = true

  const chatContent = document.getElementById("chatContent")
  const scrollHeight = chatContent.scrollHeight // 页面内容高度

  socket.emit("single_history_msg", request, ({data}) => {
    dealMsg(data, activeContact.value.casId, true)
    if (data.length < 10) {
      activeContact.value.isEnd = true
    }
    activeContact.value.loading = false

    nextTick(() => {
      chatContent.scrollTop = chatContent.scrollHeight - scrollHeight // 滚动条距离
    })

  })
}

async function dealMsg(msgs, renderCasId, isHistoryMsg) {

  var fromContact = undefined;
  for (let i = 0; i < contactList.value.length; i++) {
    const contact = contactList.value[i];
    if (contact.casId == renderCasId) {
      fromContact = contact;
      break
    }
  }
  if (fromContact == undefined) {

    fromContact = await new Promise(resolve => {
      socket.emit("contact_info", msgs[0], ({data}) => {
        fromContact = data
        resolve(data)
      })
    });

    initContact(fromContact)
    contactList.value.push(fromContact)
  }

  for (let i = 0; i < msgs.length; i++) {
    const msg = msgs[i];
    if (msg.toUser == renderCasId) {
      if (!fromContact.sendIdSet.has(msg.id)) {
        msg.isSelfSend = true;
        if (isHistoryMsg) {
          fromContact.msgList.unshift(msg)
        } else {
          fromContact.msgList.push(msg);
        }
        fromContact.sendIdSet.add(msg.id)
        if (fromContact.beforeSendId == null || fromContact.beforeSendId > msg.id) {
          fromContact.beforeSendId = msg.id
        }
      }
    } else {
      if (!fromContact.receiveIdSet.has(msg.id)) {
        msg.isSelfSend = false;
        if (isHistoryMsg) {
          fromContact.msgList.unshift(msg)
        } else {
          fromContact.msgList.push(msg);
        }
        fromContact.receiveIdSet.add(msg.id)
        if (fromContact.beforeReceiveId == null || fromContact.beforeReceiveId > msg.id) {
          fromContact.beforeReceiveId = msg.id
        }
      }
    }
  }
}

const sendMsg = () => {
  const request = {
    "fromUser": myCasId,
    "toUser": activeContact.value.casId,
    "content": sendText.value,
    "contentType": 0,
    "msgType": 0,
  }
  socket.emit("single_chat", request, ({data}) => {
    const msgs = [data]
    dealMsg(msgs, activeContact.value.casId, false);
    sendText.value = ''
    toBottom()
  })
}
// -----------------------------event-----------------------------------------
const tabClick = (casId) => {

  for (let i = 0; i < contactList.value.length; i++) {
    const contact = contactList.value[i];
    if (contact.casId == casId) {
      activeContact.value = contact
    }
  }

  nextTick(() => {
    const chatContent = document.getElementById("chatContent")
    chatContent.scrollTop = Number.MAX_SAFE_INTEGER
    handleScroll()
  })
}
const handleScroll = () => {
  const chatContent = document.getElementById("chatContent")
  const scrollTop = chatContent.scrollTop // 页面滚动的高度
  if (scrollTop == 0 && !activeContact.value.isEnd) {
    fetchMsgHistory()
  }
};
const toBottom = () => {
  nextTick(() => {
    const chatContent = document.getElementById("chatContent")
    chatContent.scrollTop = chatContent.scrollHeight
  })
}
// --------------------------------------------


</script>
<style>
</style>

